iT邦幫忙

第 12 屆 iThome 鐵人賽

DAY 18
0
Elastic Stack on Cloud

Elastic 戰台股系列 第 18

[Day18] 選股策略實作 - Script Query (1)

  • 分享至 

  • xImage
  •  

連續兩天的選股實作圍繞著搜尋,今天把選股程式整合結果寫出來,然後為嘗試不同的搜尋方法起個頭。

選股程式完成版

結合前兩天的內容,今天把第一個完整的選股程式和結果分享出來。

Step 1: 搜尋最新的盤後資訊與移動平均資訊

利用兩個 MultiSearch 物件分別取回最新一筆盤後資訊與移動平均指標。

ms_daily = MultiSearch(using=es)
ms_sma = MultiSearch(using=es)

for stock_id in stock_id_list: 
    search_daily = Search(index='history-prices-daily').\
        query("match", stock_id=stock_id).\
        source(includes=['stock_id', 'date', 'close', 'volume']).\
        sort({"date": {"order": "desc"}})
    search_daily = search_daily[0:1]    
    ms_daily = ms_daily.add(search_daily)

    search_sma = Search(index='tech-analysis-sma').\
        query("match", stock_id=stock_id).\
        source(includes=['stock_id', 'date', 'close_sma_100', 'volume_sma_20']).\
        sort({"date": {"order": "desc"}})
    search_sma = search_sma[0:1]    
    ms_sma = ms_sma.add(search_sma)
    
responses_daily = ms_daily.execute()
responses_sma = ms_sma.execute()

Step 2: 將搜尋結果轉換成 Pandas.Dataframe

def response_to_dataframe(es_multi_responses):
    doc_fields = {}
    count = 0
    for response in es_multi_responses:
        count += 1
        if not bool(response):
            continue
        source_data = response["hits"]["hits"][0]["_source"]
        for key in source_data:
            try:
                doc_fields[key] = np.append(doc_fields[key], source_data[key])
            except KeyError:
                doc_fields[key] = np.array([source_data[key]])
    return pd.DataFrame(doc_fields)

elastic_df_daily = response_to_dataframe(responses_daily)
elastic_df_sma = response_to_dataframe(responses_sma)

elastic_df_merge = pd.merge(elastic_df_daily, elastic_df_sma, on=['stock_id','date'])

Step 3: 利用 Pandas 進行選股

選股邏輯為:收盤價大於 100 線,且成交量大於月均量 1.5 倍。

elastic_df_merge['Qualify'] = np.where(
(elastic_df_merge['volume'].astype(np.float) >= 1.5 * elastic_df_merge['volume_sma_20'].astype(np.float)) &
(elastic_df_merge['close'].astype(np.float) >=elastic_df_merge['close_sma_100'].astype(np.float)),                                    True, False)
                  
df_select = elastic_df_merge.loc[elastic_df_merge['Qualify'] == True]
print(df_select)

結果如下:
https://ithelp.ithome.com.tw/upload/images/20201001/20129624MFWTlgiJDq.png
共找到 137 檔個股符合條件。

把運算交給 ElasticSearch

利用 Python client 的確可以達到我想要結果,但我不禁懷疑,是否可以把邏輯交給 ES 運算呢?經過一翻研究,我發現了 ES 提供 script query 的功能,也就是把 Script 寫在 Query DSL,就可以執行一些邏輯運算。以下的官方文件的一個範例:

GET /_search
{
  "query": {
    "bool": {
      "filter": {
        "script": {
          "script": {
            "source": "doc['num1'].value > 1",
            "lang": "painless"
          }
        }
      }
    }
  }
}

從上面的代碼,馬上就發現了要探索的新東西:"painless",我好興奮啊!

今天先到這了,明天開始繼續進化我的選股程式。


上一篇
[Day17] 選股策略實作 - Multi Search API
下一篇
[Day19] 選股程式實作 - Script Query (2)
系列文
Elastic 戰台股30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言